home *** CD-ROM | disk | FTP | other *** search
- /* tty.c -- The tty management file. */
-
- /* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Written by Tudor Hulubei and Andrei Pitis. */
-
-
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
-
- #include <stdio.h>
-
- #ifdef HAVE_STDLIB_H
- #include <stdlib.h>
- #else /* !HAVE_STDLIB_H */
- #include "ansi_stdlib.h"
- #endif /* !HAVE_STDLIB_H */
-
- #include <sys/types.h>
- #include <ctype.h>
- #include "file.h"
- #include <sys/ioctl.h>
-
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif /* HAVE_UNISTD_H */
-
- #include "stdc.h"
- #include "xstring.h"
- #include "xmalloc.h"
- #include "xio.h"
- #include "tty.h"
- #include "misc.h"
-
-
- /* Stolen from GNU Emacs. */
- #ifdef _POSIX_VDISABLE
- #define CDISABLE _POSIX_VDISABLE
- #else /* not _POSIX_VDISABLE */
- #ifdef CDEL
- #undef CDISABLE
- #define CDISABLE CDEL
- #else /* not CDEL */
- #define CDISABLE 255
- #endif /* not CDEL */
- #endif /* not _POSIX_VDISABLE */
-
- #define MAX_TTY_COLUMNS 512
- #define MIN_TTY_COLUMNS 80
- #define MAX_TTY_LINES 512
- #define MIN_TTY_LINES 8
-
-
- /* I want to avoid including curses.h or any other header file that
- defines these. I think it's safer because I couldn't find 2
- similar curses.h files in the entire world... */
-
- int tputs PROTO ((const char *__string, int __nlines, int (*outfun)()));
- int tgetent PROTO ((void *__buffer, const char *__termtype));
- char *tgetstr PROTO ((const char *__name, char **__area));
- int tgetnum PROTO ((const char *__name));
- int tgetflag PROTO ((const char *__name));
- char *tgoto PROTO ((const char *__cstring, int __hpos, int __vpos));
-
-
- #define TTY_INPUT 0
- #define TTY_OUTPUT 1
-
- #ifdef HAVE_LINUX
- #define VCS_READ 1
- #define VCS_WRITE 2
- #endif
-
- #ifdef HAVE_LINUX
- static int vcs_read_ok;
- static int vcs_is_bw;
- #endif
-
- /* If tty_kbdmode == 1, single characters are inserted in the linked list.
- This feature is used by gitps (it has no command line). */
- static int tty_kbdmode;
-
- #ifdef HAVE_POSIX_TTY
- static struct termios old_term;
- static struct termios new_term;
- #else
- #ifdef HAVE_SYSTEMV_TTY
- static struct termio old_term;
- static struct termio new_term;
- #else
- static struct sgttyb old_arg;
- static struct tchars old_targ;
- static struct ltchars old_ltarg;
- static struct sgttyb new_arg;
- static struct tchars new_targ;
- static struct ltchars new_ltarg;
-
- /* NextStep doesn't define TILDE. */
- #ifndef TILDE
- #define TILDE 0
- #endif
-
- #endif /* HAVE_SYSTEMV_TTY */
- #endif /* HAVE_POSIX_TTY */
-
- static int lines, columns;
-
- static tty_last_char_flag;
-
- static int tty_cursor_x;
- static int tty_cursor_y;
-
- /*
- * tty_*_current_attribute: bit 7: reverse video
- * bit 6: brightness
- * bits 5,4,3: background color
- * bits 2,1,0: foreground color
- */
- static unsigned char tty_current_attribute;
- static unsigned char tty_io_current_attribute;
-
- #define INVALID_CACHE 0
- #define VALID_CACHE 1
-
- static int fg_cache = INVALID_CACHE;
- static int bg_cache = INVALID_CACHE;
- static int br_cache = INVALID_CACHE;
- static int rv_cache = INVALID_CACHE;
-
- /* tty_scr the current status of the screen, while tty_atr is used to
- keep the current status of the attributes. */
- static unsigned char *tty_scr = NULL;
- static unsigned char *tty_atr = NULL;
-
- /* tty_prev_scr will always contain the copy of the previous screen,
- while tty_atr will contain the copy of the previous attributes. */
- static unsigned char *tty_prev_scr = NULL;
- static unsigned char *tty_prev_atr = NULL;
-
-
- /* The ANSI color sequences. */
- static char ansi_foreground[] = { 0x1b, '[', '3', '0', 'm' };
- static char ansi_background[] = { 0x1b, '[', '4', '0', 'm' };
- static char ansi_defaults[] = { 0x1b, '[', '0', 'm' };
-
- /* These variable tells us if we should use standard ANSI color sequences.
- Its value is taken from the configuration file. */
- extern int AnsiColors;
-
- #define FOREGROUND_MASK 0x07
- #define BACKGROUND_MASK 0x38
- #define BRIGHTNESS_MASK 0x40
- #define REVERSEVID_MASK 0x80
-
-
- #define _TTY_FOREGROUND(attributes) (((attributes) & FOREGROUND_MASK) >> 0)
- #define _TTY_BACKGROUND(attributes) (((attributes) & BACKGROUND_MASK) >> 3)
- #define _TTY_BRIGHTNESS(attributes) (((attributes) & BRIGHTNESS_MASK) >> 6)
- #define _TTY_REVERSEVID(attributes) (((attributes) & REVERSEVID_MASK) >> 7)
-
- #define TTY_IO_FOREGROUND _TTY_FOREGROUND(tty_io_current_attribute)
- #define TTY_IO_BACKGROUND _TTY_BACKGROUND(tty_io_current_attribute)
- #define TTY_IO_BRIGHTNESS _TTY_BRIGHTNESS(tty_io_current_attribute)
- #define TTY_IO_REVERSEVID _TTY_REVERSEVID(tty_io_current_attribute)
-
- #define TTY_FOREGROUND _TTY_FOREGROUND(tty_current_attribute)
- #define TTY_BACKGROUND _TTY_BACKGROUND(tty_current_attribute)
- #define TTY_BRIGHTNESS _TTY_BRIGHTNESS(tty_current_attribute)
- #define TTY_REVERSEVID _TTY_REVERSEVID(tty_current_attribute)
-
- #define _TTY_SET_FOREGROUND(attributes, color)\
- ((attributes) = ((attributes) & ~FOREGROUND_MASK) | (((color) & 7) << 0))
- #define _TTY_SET_BACKGROUND(attributes, color)\
- ((attributes) = ((attributes) & ~BACKGROUND_MASK) | (((color) & 7) << 3))
- #define _TTY_SET_BRIGHTNESS(attributes, status)\
- ((attributes) = ((attributes) & ~BRIGHTNESS_MASK) | (((status) & 1) << 6))
- #define _TTY_SET_REVERSEVID(attributes, status)\
- ((attributes) = ((attributes) & ~REVERSEVID_MASK) | (((status) & 1) << 7))
-
- #define TTY_IO_SET_FOREGROUND(color)\
- _TTY_SET_FOREGROUND(tty_io_current_attribute, (color))
- #define TTY_IO_SET_BACKGROUND(color)\
- _TTY_SET_BACKGROUND(tty_io_current_attribute, (color))
- #define TTY_IO_SET_BRIGHTNESS(status)\
- _TTY_SET_BRIGHTNESS(tty_io_current_attribute, (status))
- #define TTY_IO_SET_REVERSEVID(status)\
- _TTY_SET_REVERSEVID(tty_io_current_attribute, (status))
-
- #define TTY_SET_FOREGROUND(color)\
- _TTY_SET_FOREGROUND(tty_current_attribute, (color))
- #define TTY_SET_BACKGROUND(color)\
- _TTY_SET_BACKGROUND(tty_current_attribute, (color))
- #define TTY_SET_BRIGHTNESS(status)\
- _TTY_SET_BRIGHTNESS(tty_current_attribute, (status))
- #define TTY_SET_REVERSEVID(status)\
- _TTY_SET_REVERSEVID(tty_current_attribute, (status))
-
-
- #ifdef HAVE_LINUX
- /* These variable tells us if we are using a Linux console. */
- int LinuxConsole;
- #endif /* HAVE_LINUX */
-
-
- /* Structures for keys management. */
- tty_key_t *key_list_head = NULL;
- tty_key_t *current_key;
- tty_key_t default_key;
-
- /* 10 Kb of cache memory for terminal optimizations. */
- #define TTY_CACHE_SIZE 10240
-
- static char tty_cache[TTY_CACHE_SIZE];
- static unsigned int tty_index;
-
- static char term_buf[2048];
- static char vt100[] = "vt100";
-
- /* The terminal mode. TTY_CANONIC at the begining. */
- int tty_mode = TTY_CANONIC;
-
- char *tty_type;
-
- char PC; /* For tputs. */
- char *BC; /* For tgoto/tparm. */
- char *UP;
-
- #ifdef HAVE_LINUX
- speed_t ospeed;
- #else /* !HAVE_LINUX */
- short ospeed;
- #endif /* !HAVE_LINUX */
-
-
- /* A structure describing some attributes we need to know about each
- capability. See below for greater detail. */
- typedef struct
- {
- char *name; /* the capability name. */
-
- /* These ones should be in an union, but the HP-UX non ANSI compiler
- complains about union initialization being an ANSI feature and I
- care more for portability than for the memory used. */
- char *string; /* The string value of the capability. */
- int integer; /* The integer value of the capability. */
-
- int required; /* This capability is required. */
- char *symbol; /* The human readable form of the key name. */
- } TTY_CAPABILITY;
-
-
- #define TTY_USED_CAPABILITIES 34
- #define TTY_FIRST_SYMBOL_KEY 13
-
- static TTY_CAPABILITY tty_capability[TTY_USED_CAPABILITIES] =
- {
- { "me", NULL, 0, 0, NULL }, /* turn off all attributes */
- { "mr", NULL, 0, 0, NULL }, /* turn on reverse video mode */
- { "md", NULL, 0, 0, NULL }, /* turn on bold */
- { "vi", NULL, 0, 0, NULL }, /* make the cursor invisible */
- { "ve", NULL, 0, 0, NULL }, /* make the cursor appear normal */
- { "cl", NULL, 0, 1, NULL }, /* clear screen & home the cursor */
- { "cm", NULL, 0, 1, NULL }, /* move the cursor */
- { "pc", NULL, 0, 0, NULL }, /* padding character */
- { "up", NULL, 0, 0, NULL }, /* up one line */
- { "le", NULL, 0, 0, NULL }, /* move left one space */
- { "so", NULL, 0, 0, NULL }, /* enter standout mode. */
- { "sg", NULL, 0, 0, NULL }, /* this is a magic-cookie terminal. */
- { "ms", NULL, 0, 0, NULL }, /* safe to move in standout mode. */
- { "ku", NULL, 0, 0, "UP" }, /* (UP) */
- { "kd", NULL, 0, 0, "DOWN" }, /* (DOWN) */
- { "kr", NULL, 0, 0, "RIGHT" }, /* (RIGHT) */
- { "kl", NULL, 0, 0, "LEFT" }, /* (LEFT) */
- { "kI", NULL, 0, 0, "INS" }, /* (INS) */
- { "kD", NULL, 0, 0, "DEL" }, /* (DEL) */
- { "kh", NULL, 0, 0, "HOME" }, /* (HOME) */
- { "kH", NULL, 0, 0, "END" }, /* (END) */
- { "kP", NULL, 0, 0, "PGUP" }, /* (PGUP) */
- { "kN", NULL, 0, 0, "PGDOWN" }, /* (PGDOWN) */
- { "k0", NULL, 0, 0, "F0" }, /* (F0) */
- { "k1", NULL, 0, 0, "F1" }, /* (F1) */
- { "k2", NULL, 0, 0, "F2" }, /* (F2) */
- { "k3", NULL, 0, 0, "F3" }, /* (F3) */
- { "k4", NULL, 0, 0, "F4" }, /* (F4) */
- { "k5", NULL, 0, 0, "F5" }, /* (F5) */
- { "k6", NULL, 0, 0, "F6" }, /* (F6) */
- { "k7", NULL, 0, 0, "F7" }, /* (F7) */
- { "k8", NULL, 0, 0, "F8" }, /* (F8) */
- { "k9", NULL, 0, 0, "F9" }, /* (F9) */
- { "k;", NULL, 0, 0, "F10" }, /* (F10) */
- };
-
-
- /* Some nice aliases... */
- #define TTY_ATTRIBUTES_OFF (tty_capability[0].string)
- #define TTY_REVERSE_ON (tty_capability[1].string)
- #define TTY_BRIGHT_ON (tty_capability[2].string)
- #define TTY_CURSOR_OFF (tty_capability[3].string)
- #define TTY_CURSOR_ON (tty_capability[4].string)
- #define TTY_CLEAR_SCREEN (tty_capability[5].string)
- #define TTY_CURSOR_MOVE (tty_capability[6].string)
- #define TTY_PAD_CHAR (tty_capability[7].string)
- #define TTY_UP_ONE_LINE (tty_capability[8].string)
- #define TTY_LEFT_ONE_SPACE (tty_capability[9].string)
- #define TTY_STANDOUT_ON (tty_capability[10].string)
- #define TTY_MAGIC_COOKIE (tty_capability[11].integer)
- #define TTY_MS_FLAG (tty_capability[12].integer)
-
-
- /* Some more nice aliases. */
- #define TTY_ATTRIBUTES_OFF_NAME (tty_capability[0].name)
- #define TTY_REVERSE_ON_NAME (tty_capability[1].name)
- #define TTY_BRIGHT_ON_NAME (tty_capability[2].name)
- #define TTY_CURSOR_OFF_NAME (tty_capability[3].name)
- #define TTY_CURSOR_ON_NAME (tty_capability[4].name)
- #define TTY_CLEAR_SCREEN_NAME (tty_capability[5].name)
- #define TTY_CURSOR_MOVE_NAME (tty_capability[6].name)
- #define TTY_PAD_CHAR_NAME (tty_capability[7].name)
- #define TTY_UP_ONE_LINE_NAME (tty_capability[8].name)
- #define TTY_LEFT_ONE_SPACE_NAME (tty_capability[9].name)
- #define TTY_STANDOUT_ON_NAME (tty_capability[10].name)
- #define TTY_MAGIC_COOKIE_NAME (tty_capability[11].name)
- #define TTY_MS_FLAG_NAME (tty_capability[12].name)
-
-
- #ifdef HAVE_LIBTERMCAP
-
- static char term_database[] = "termcap";
- static char term_env[] = "TERMCAP";
-
- #else /* !HAVE_LIBTERMCAP */
-
- static char term_database[] = "terminfo";
- static char term_env[] = "TERMINFO";
-
- #endif /* !HAVE_LIBTERMCAP */
-
-
- static void tty_io_goto PROTO ((int, int));
- static void tty_io_foreground PROTO ((int));
- static void tty_io_background PROTO ((int));
- static void tty_io_brightness PROTO ((int));
- static void tty_io_reversevid PROTO ((int));
- static void tty_io_colors PROTO ((unsigned char));
-
-
- void fatal PROTO ((char *));
-
-
- /* ANSI colors. OFF & ON are here because we need them when we read the
- configuration file. Don't bother... */
- static char *colors[10] =
- {
- "BLACK",
- "RED",
- "GREEN",
- "YELLOW",
- "BLUE",
- "MAGENTA",
- "CYAN",
- "WHITE",
- "OFF",
- "ON"
- };
-
-
- /* Control keys description. C-a, C-b, C-c and so on... */
- unsigned char key_ctrl_table[0x5f] =
- {
- 0x20, /* 0x20 ( ) */
- 0x21, /* 0x21 (!) */
- 0x22, /* 0x22 (") */
- 0x23, /* 0x23 (#) */
- 0xff, /* 0x24 ($) */
- 0x25, /* 0x25 (%) */
- 0x26, /* 0x26 (&) */
- 0x07, /* 0x27 (') */
- 0x28, /* 0x28 (() */
- 0x29, /* 0x29 ()) */
- 0x2a, /* 0x2a (*) */
- 0x2b, /* 0x2b (+) */
- 0x2c, /* 0x2c (,) */
- 0x2d, /* 0x2d (-) */
- 0x2e, /* 0x2e (.) */
- 0x2f, /* 0x2f (/) */
- 0x20, /* 0x30 (0) */
- 0x20, /* 0x31 (1) */
- 0xff, /* 0x32 (2) */
- 0x1b, /* 0x33 (3) */
- 0x1c, /* 0x34 (4) */
- 0x1d, /* 0x35 (5) */
- 0x1e, /* 0x36 (6) */
- 0x1f, /* 0x37 (7) */
- 0x7f, /* 0x38 (8) */
- 0x39, /* 0x39 (9) */
- 0x3a, /* 0x3a (:) */
- 0x3b, /* 0x3b (;) */
- 0x3c, /* 0x3c (<) */
- 0x20, /* 0x3d (=) */
- 0x3e, /* 0x3e (>) */
- 0x20, /* 0x3f (?) */
- 0x20, /* 0x40 (@) */
- 0x01, /* 0x41 (A) */
- 0x02, /* 0x42 (B) */
- 0x03, /* 0x43 (C) */
- 0x04, /* 0x44 (D) */
- 0x05, /* 0x45 (E) */
- 0x06, /* 0x46 (F) */
- 0x07, /* 0x47 (G) */
- 0x08, /* 0x48 (H) */
- 0x09, /* 0x49 (I) */
- 0x0a, /* 0x4a (J) */
- 0x0b, /* 0x4b (K) */
- 0x0c, /* 0x4c (L) */
- 0x0d, /* 0x4d (M) */
- 0x0e, /* 0x4e (N) */
- 0x0f, /* 0x4f (O) */
- 0x10, /* 0x50 (P) */
- 0x11, /* 0x51 (Q) */
- 0x12, /* 0x52 (R) */
- 0x13, /* 0x53 (S) */
- 0x14, /* 0x54 (T) */
- 0x15, /* 0x55 (U) */
- 0x16, /* 0x56 (V) */
- 0x17, /* 0x57 (W) */
- 0x18, /* 0x58 (X) */
- 0x19, /* 0x59 (Y) */
- 0x1a, /* 0x5a (Z) */
- 0x1b, /* 0x5b ([) */
- 0x1c, /* 0x5c (\) */
- 0x1d, /* 0x5d (]) */
- 0x5e, /* 0x5e (^) */
- 0x7f, /* 0x5f (_) */
- 0x20, /* 0x60 (`) */
- 0x01, /* 0x61 (a) */
- 0x02, /* 0x62 (b) */
- 0x03, /* 0x63 (c) */
- 0x04, /* 0x64 (d) */
- 0x05, /* 0x65 (e) */
- 0x06, /* 0x66 (f) */
- 0x07, /* 0x67 (g) */
- 0x08, /* 0x68 (h) */
- 0x09, /* 0x69 (i) */
- 0x0a, /* 0x6a (j) */
- 0x0b, /* 0x6b (k) */
- 0x0c, /* 0x6c (l) */
- 0x0d, /* 0x6d (m) */
- 0x0e, /* 0x6e (n) */
- 0x0f, /* 0x6f (o) */
- 0x10, /* 0x70 (p) */
- 0x11, /* 0x71 (q) */
- 0x12, /* 0x72 (r) */
- 0x13, /* 0x73 (s) */
- 0x14, /* 0x74 (t) */
- 0x15, /* 0x75 (u) */
- 0x16, /* 0x76 (v) */
- 0x17, /* 0x77 (w) */
- 0x18, /* 0x78 (x) */
- 0x19, /* 0x79 (y) */
- 0x1a, /* 0x7a (z) */
- 0x20, /* 0x7b ({) */
- 0x20, /* 0x7c (|) */
- 0x20, /* 0x7d (}) */
- 0x20, /* 0x7e (~) */
- };
-
-
- #define NO 0
- #define YES 1
-
- #define MAX_KEY_LENGTH 15
-
- /* Major number for Linux virtual console devices (/dev/tty*). */
- #define LINUX_VC_MAJOR 4
-
-
- static int keyno = 0;
- static int keyindex = 0;
- static char keybuf[1024];
-
-
- /* Hooks that get called when we are going idle and when we stop
- being idle. */
- void (* tty_enter_idle_hook)() = NULL;
- void (* tty_exit_idle_hook)() = NULL;
-
-
- void
- tty_startup(last_char)
- int last_char;
- {
- /* Fail if stdin or stdout are not real terminals. */
- if (!isatty(TTY_INPUT) || !isatty(TTY_OUTPUT))
- fatal("only standard error can be redirected");
-
- /* Get calloc-ed memory for tty_scr & tty_atr. */
- tty_scr = (unsigned char *)xcalloc(columns * lines,
- sizeof(unsigned char));
- tty_atr = (unsigned char *)xcalloc(columns * lines,
- sizeof(unsigned char));
-
- /* Get calloc-ed memory for tty_prev_scr & tty_prev_atr. */
- tty_prev_scr = (unsigned char *)xcalloc(columns * lines,
- sizeof(unsigned char));
- tty_prev_atr = (unsigned char *)xcalloc(columns * lines,
- sizeof(unsigned char));
-
- /* Store the terminal settings in old_term. it will be used to restore
- them later. */
- #ifdef HAVE_POSIX_TTY
- tcgetattr(TTY_OUTPUT, &old_term);
- #else
- #ifdef HAVE_SYSTEMV_TTY
- ioctl(TTY_OUTPUT, TCGETA, &old_term);
- #else
- ioctl(TTY_OUTPUT, TIOCGETP, &old_arg);
- ioctl(TTY_OUTPUT, TIOCGETC, &old_targ);
- ioctl(TTY_OUTPUT, TIOCGLTC, &old_ltarg);
- #endif /* HAVE_SYSTEMV_TTY */
- #endif /* HAVE_POSIX_TTY */
-
- tty_last_char_flag = last_char;
- }
-
-
- /*
- * Initialize some keybord stuff.
- */
-
- void
- tty_kbdinit(kbd_mode)
- int kbd_mode;
- {
- default_key.key_seq = (unsigned char *)xmalloc(16);
- default_key.aux_data = NULL;
- default_key.next = NULL;
- tty_kbdmode = kbd_mode;
- }
-
-
- /*
- * This function is used to switch between canonical and noncanonical
- * terminal modes.
- */
-
- void
- tty_set_mode(mode)
- int mode;
- {
- if (mode == TTY_NONCANONIC)
- {
- #ifdef HAVE_POSIX_TTY
- new_term = old_term;
- new_term.c_iflag &= ~(IXON | ICRNL | IGNCR | INLCR | IGNBRK | BRKINT);
- new_term.c_oflag &= ~OPOST;
- new_term.c_lflag |= ISIG | NOFLSH;
- new_term.c_lflag &= ~(ICANON | ECHO);
-
- /* I think we will always have these ones: */
-
- new_term.c_cc[VINTR] = key_INTERRUPT; /* Ctrl-G */
- new_term.c_cc[VQUIT] = key_INTERRUPT; /* Ctrl-G */
-
- #ifdef VSTART
- new_term.c_cc[VSTART] = CDISABLE; /* START (^Q) */
- #endif
-
- #ifdef VSTOP
- new_term.c_cc[VSTOP] = CDISABLE; /* STOP (^S) */
- #endif
-
- new_term.c_cc[VMIN] = 1;
- new_term.c_cc[VTIME] = 0;
-
- /* ... but not always these ones: (in fact I am not sure if I
- really need to overwrite all these, but just in case... */
-
- #ifdef VERASE
- new_term.c_cc[VERASE] = CDISABLE;
- #endif
-
- #ifdef VKILL
- new_term.c_cc[VKILL] = CDISABLE;
- #endif
-
- #ifdef VEOL
- new_term.c_cc[VEOL] = CDISABLE;
- #endif
-
- #ifdef VEOL2
- new_term.c_cc[VEOL2] = CDISABLE;
- #endif
-
- #ifdef VSWTCH
- new_term.c_cc[VSWTCH] = CDISABLE;
- #endif
-
- #ifdef VSUSP
- new_term.c_cc[VSUSP] = key_SUSPEND; /* Ctrl-Z */
- #endif
-
- #ifdef VDSUSP
- new_term.c_cc[VDSUSP] = CDISABLE;
- #endif
-
- #ifdef VREPRINT
- new_term.c_cc[VREPRINT] = CDISABLE;
- #endif
-
- #ifdef VDISCARD
- new_term.c_cc[VDISCARD] = CDISABLE;
- #endif
-
- #ifdef VWERASE
- new_term.c_cc[VWERASE] = CDISABLE;
- #endif
-
- #ifdef VLNEXT
- new_term.c_cc[VLNEXT] = CDISABLE;
- #endif
-
- tcsetattr(TTY_OUTPUT, TCSADRAIN, &new_term);
- ospeed = cfgetospeed(&new_term);
- #else
- #ifdef HAVE_SYSTEMV_TTY
- new_term = old_term;
- new_term.c_iflag &= ~(IXON | ICRNL | IGNCR | INLCR);
- new_term.c_oflag = 0;
- new_term.c_lflag = 0;
-
- /* I think we will always have these: */
-
- new_term.c_cc[VINTR] = key_INTERRUPT; /* Ctrl-G */
- new_term.c_cc[VQUIT] = key_INTERRUPT; /* Ctrl-G */
-
- #ifdef VSTART
- new_term.c_cc[VSTART] = CDISABLE; /* START (^Q) */
- #endif
-
- #ifdef VSTOP
- new_term.c_cc[VSTOP] = CDISABLE; /* STOP (^S) */
- #endif
-
- new_term.c_cc[VMIN] = 1;
- new_term.c_cc[VTIME] = 0;
-
- /* ... but not always these: (in fact I am not sure if I really
- need to overwrite all these, but just in case... */
-
- #ifdef VERASE
- new_term.c_cc[VERASE] = CDISABLE;
- #endif
-
- #ifdef VKILL
- new_term.c_cc[VKILL] = CDISABLE;
- #endif
-
- #ifdef VEOL
- new_term.c_cc[VEOL] = CDISABLE;
- #endif
-
- #ifdef VEOL2
- new_term.c_cc[VEOL2] = CDISABLE;
- #endif
-
- #ifdef VSWTCH
- new_term.c_cc[VSWTCH] = CDISABLE;
- #endif
-
- #ifdef VSUSP
- new_term.c_cc[VSUSP] = key_SUSPEND; /* Ctrl-Z */
- #endif
-
- #ifdef VDSUSP
- new_term.c_cc[VDSUSP] = CDISABLE;
- #endif
-
- #ifdef VREPRINT
- new_term.c_cc[VREPRINT] = CDISABLE;
- #endif
-
- #ifdef VDISCARD
- new_term.c_cc[VDISCARD] = CDISABLE;
- #endif
-
- #ifdef VWERASE
- new_term.c_cc[VWERASE] = CDISABLE;
- #endif
-
- #ifdef VLNEXT
- new_term.c_cc[VLNEXT] = CDISABLE;
- #endif
-
- ioctl(TTY_OUTPUT, TCSETAW, &new_term);
- ospeed = new_term.c_cflag & CBAUD;
- #else
- new_arg = old_arg;
- new_targ = old_targ;
- new_ltarg = old_ltarg;
- new_arg.sg_flags = ((old_arg.sg_flags &
- ~(ECHO | CRMOD | XTABS | ALLDELAY | TILDE)) | CBREAK);
- new_targ.t_intrc = key_INTERRUPT; /* Ctrl-G */
- new_targ.t_quitc = key_INTERRUPT; /* Ctrl-G */
- new_targ.t_stopc = CDISABLE; /* Ctrl-G */
- new_targ.t_startc = CDISABLE; /* Ctrl-G */
- new_targ.t_eofc = CDISABLE;
- new_targ.t_brkc = CDISABLE;
- new_ltarg.t_lnextc = CDISABLE;
- new_ltarg.t_flushc = CDISABLE;
- new_ltarg.t_werasc = CDISABLE;
- new_ltarg.t_rprntc = CDISABLE;
- new_ltarg.t_dsuspc = CDISABLE; /* DSUSPC (delayed SUSPC,^Y) */
- new_ltarg.t_suspc = key_SUSPEND;
-
- ioctl(TTY_OUTPUT, TIOCSETN, &new_arg);
- ioctl(TTY_OUTPUT, TIOCSETC, &new_targ);
- ioctl(TTY_OUTPUT, TIOCSLTC, &new_ltarg);
- ospeed = new_arg.sg_ospeed;
- #endif /* HAVE_SYSTEMV_TTY */
- #endif /* HAVE_POSIX_TTY */
-
- /* Try to make sure the terminal is not locked. */
- #ifdef TCXONC
- #ifdef __QNX__
- {
- int value = 1;
- ioctl (TTY_OUTPUT, TCXONC, &value);
- }
- #else
- ioctl(TTY_OUTPUT, TCXONC, 1);
- #endif
- #endif
-
- #ifndef APOLLO
- #ifdef TIOCSTART
- ioctl(TTY_OUTPUT, TIOCSTART, 0);
- #endif
- #endif
-
- #ifdef HAVE_POSIX_TTY
- #ifdef TCOON
- tcflow(TTY_OUTPUT, TCOON);
- #endif
- #endif
- }
- else
- {
- #ifdef HAVE_POSIX_TTY
- tcsetattr(TTY_OUTPUT, TCSADRAIN, &old_term);
- #else
- #ifdef HAVE_SYSTEMV_TTY
- ioctl(TTY_OUTPUT, TCSETAW, &old_term);
- #else
- ioctl(TTY_OUTPUT, TIOCSETN, &old_arg);
- ioctl(TTY_OUTPUT, TIOCSETC, &old_targ);
- ioctl(TTY_OUTPUT, TIOCSLTC, &old_ltarg);
- #endif /* HAVE_SYSTEMV_TTY */
- #endif /* HAVE_POSIX_TTY */
- }
-
- tty_mode = mode;
- }
-
-
- /*
- * Set the interrupt character.
- */
-
- void
- tty_set_interrupt_char(c)
- unsigned char c;
- {
- #ifdef HAVE_POSIX_TTY
- struct termios current_term;
-
- tcgetattr(TTY_OUTPUT, ¤t_term);
- current_term.c_cc[VINTR] = c;
- current_term.c_cc[VQUIT] = c;
- tcsetattr(TTY_OUTPUT, TCSADRAIN, ¤t_term);
- #else
- #ifdef HAVE_SYSTEMV_TTY
- struct termio current_term;
-
- ioctl(TTY_OUTPUT, TCGETA, ¤t_term);
- current_term.c_cc[VINTR] = c;
- current_term.c_cc[VQUIT] = c;
- ioctl(TTY_OUTPUT, TCSETAW, ¤t_term);
- #else
- struct tchars current_targ;
-
- ioctl(TTY_OUTPUT, TIOCGETC, ¤t_targ);
- current_targ.t_intrc = c;
- current_targ.t_quitc = c;
- ioctl(TTY_OUTPUT, TIOCSETC, ¤t_targ);
- #endif /* HAVE_SYSTEMV_TTY */
- #endif /* HAVE_POSIX_TTY */
- }
-
-
- /*
- * Write a character to the screen. Used by tputs() to output
- * characters. Actually we are only storing them in a buffer
- * (tty_cache[]) and flush them later (in tty_flush()).
- */
-
- int
- tty_writec(c)
- int c;
- {
- tty_cache[tty_index++] = (char)c;
- return 1;
- }
-
-
- /*
- * Send the `cl' sequence to the terminal.
- */
-
- void
- tty_io_clear()
- {
- tputs(TTY_CLEAR_SCREEN, lines, tty_writec);
- tty_flush();
- }
-
-
- /*
- * This function is called to restore the canonic mode at exit. It also
- * clears the screen (or restore it, if possible) and sets the default
- * attributes. If screen is NULL, there was an error, so don't try to
- * restore it.
- */
-
- void
- tty_exit(screen)
- char *screen;
- {
- if (tty_mode == TTY_NONCANONIC)
- tty_set_mode(TTY_CANONIC);
-
- tty_defaults();
-
- if (screen)
- {
- #ifdef HAVE_LINUX
- if (LinuxConsole)
- tty_put_screen(screen);
- else
- tty_io_clear();
- #endif
- }
- else
- tty_io_clear();
- }
-
-
- /*
- * Converts a key sequence from the human readable, '^' based form into a
- * computer usable form.
- */
-
- char *
- tty_key_convert(key_seq)
- unsigned char *key_seq;
- {
- unsigned char *first;
- unsigned char *second;
-
-
- first = second = key_seq;
-
- if (tty_kbdmode == 0 && *key_seq != '^')
- return NULL;
-
- while (*second)
- {
- if (*second == '^')
- {
- if (*++second)
- *first++ = key_ctrl_table[(*second++ & 0x7F) - ' '];
- else
- return NULL;
- }
- else
- *first++ = *second++;
- }
-
- *first = 0;
- return (char *)key_seq;
- }
-
-
- /*
- * Flush the tty cache.
- */
-
- void
- tty_flush()
- {
- xwrite(TTY_OUTPUT, tty_cache, tty_index);
- tty_index = 0;
- }
-
-
- /*
- * Update the tty screen.
- */
-
- void
- tty_update()
- {
- int pos, x, y;
- int tty_io_cursor_x = -1;
- int tty_io_cursor_y = -1;
- int last_pos = SCREEN_X * SCREEN_Y;
-
- /* Check if we should display the last character on the screen. */
- if (tty_last_char_flag == OFF)
- last_pos--;
-
- /* Make the cursor invisible. */
- tty_cursor(OFF);
-
- for (pos = 0; pos < last_pos; pos++)
- if (tty_scr[pos] != tty_prev_scr[pos] ||
- tty_atr[pos] != tty_prev_atr[pos])
- {
- /* Move the cursor to the appropriate position, if
- necessary. */
- y = pos / SCREEN_X;
- x = pos % SCREEN_X;
-
- if (x != tty_io_cursor_x || y != tty_io_cursor_y)
- tty_io_goto(tty_io_cursor_y = y, tty_io_cursor_x = x);
-
- /* Output the color sequence, if necessary. */
- tty_io_colors(tty_atr[pos]);
-
- if (TTY_CACHE_SIZE - tty_index < 128)
- tty_flush();
-
- tty_writec(tty_scr[pos]);
-
- if (++tty_io_cursor_x == SCREEN_X)
- {
- /* Force a call to tty_io_goto(). Don't trust the tty. */
- tty_io_cursor_x = 0;
- tty_io_cursor_y = -1;
- }
- }
-
- /* Update the latest cursor position. */
- tty_io_goto(tty_cursor_y, tty_cursor_x);
-
- /* Make the cursor visible again. */
- tty_cursor(ON);
-
- if (tty_index)
- tty_flush();
-
- /* Synchronize the screen copies. */
- memcpy(tty_prev_scr, tty_scr, columns * lines * sizeof(char));
- memcpy(tty_prev_atr, tty_atr, columns * lines * sizeof(char));
- }
-
-
- /*
- * Add a string to the tty cache.
- */
-
- int
- tty_writes(s, len)
- char *s;
- size_t len;
- {
- memcpy(tty_cache + tty_index, s, len);
- tty_index += len;
- return len;
- }
-
-
- /*
- * Write a string to the screen, at the current cursor position. The
- * string should be short enough to fit into the current position and
- * the end of the line.
- */
-
- int
- tty_puts(buf, length)
- char *buf;
- size_t length;
- {
- int tty_offset = (tty_cursor_y * columns) + tty_cursor_x;
-
- memcpy(tty_scr + tty_offset, buf, length);
- memset(tty_atr + tty_offset, tty_current_attribute, length);
-
- tty_cursor_x += length;
- return length;
- }
-
-
- /*
- * Write a character to the screen.
- */
-
- int
- tty_putc(c)
- unsigned char c;
- {
- return tty_puts(&c, 1);
- }
-
-
- /*
- * Read data from the terminal.
- */
-
- size_t
- tty_read(buf, length)
- char *buf;
- size_t length;
- {
- size_t bytes;
-
- tty_update();
-
- if (tty_enter_idle_hook)
- (*tty_enter_idle_hook)();
-
- bytes = xread(TTY_INPUT, buf, length);
-
- if (tty_exit_idle_hook)
- (*tty_exit_idle_hook)();
-
- return bytes;
- }
-
-
- /*
- * Clear the screen using the current color attributes. When the
- * Linux console receives the 'cl' (clear screen) escape sequence, it
- * clears the screen using the current color attributes, while all the
- * xterms I've seen seem not to do so. Therefore, we won't rely on
- * this feature under Linux, to avoid potential problems, because I
- * don't know which approach is correct.
- */
-
- void
- tty_clear()
- {
- tty_io_clear();
-
- memset(tty_scr, '\0', lines * columns * sizeof(unsigned char));
- memset(tty_atr, '\0', lines * columns * sizeof(unsigned char));
- memset(tty_prev_scr, '\0', lines * columns * sizeof(unsigned char));
- memset(tty_prev_atr, '\0', lines * columns * sizeof(unsigned char));
-
- tty_cursor_x = 0;
- tty_cursor_y = 0;
- }
-
-
- /*
- * Fill the terminal screen with spaces & the current attribute.
- */
-
- void
- tty_fill()
- {
- memset(tty_scr, ' ',
- lines * columns * sizeof(unsigned char));
- memset(tty_atr, tty_current_attribute,
- lines * columns * sizeof(unsigned char));
-
- tty_touch();
- }
-
-
- /*
- * Touch the tty, getting rid of any possible optimization. The
- * current content of the screen will be completely different at
- * update time so that the entire screen will be updated.
- */
-
- void
- tty_touch()
- {
- memset(tty_prev_scr, '\0', lines * columns * sizeof(unsigned char));
- }
-
-
- /*
- * Move the cursor.
- */
-
- static void
- tty_io_goto(y, x)
- int y, x;
- {
- /* If the 'ms' flag is present, reset all the attributes before moving
- the cursor. */
-
- if (TTY_MS_FLAG == 0)
- tty_defaults();
-
- tputs(tgoto(TTY_CURSOR_MOVE, x, y), 1, tty_writec);
- }
-
-
- /*
- * Set the foreground color. Use the ANSI color sequence where possible or
- * tty_reverse() for monochrome terminals.
- */
-
- static void
- tty_io_foreground(color)
- int color;
- {
- char str[16];
-
- if (fg_cache == VALID_CACHE && color == TTY_IO_FOREGROUND)
- return;
-
- if (AnsiColors == ON)
- {
- memcpy(str, ansi_foreground, sizeof(ansi_foreground));
- str[3] += color;
- tty_writes(str, sizeof(ansi_foreground));
- }
- else
- tty_io_reversevid(color != WHITE);
-
- fg_cache = VALID_CACHE;
-
- TTY_IO_SET_FOREGROUND(color);
- }
-
-
- /*
- * Set the background color. Use the ANSI color sequence where possible or
- * tty_reverse() for monochrome terminals.
- */
-
- static void
- tty_io_background(color)
- int color;
- {
- char str[16];
-
- if (bg_cache == VALID_CACHE && color == TTY_IO_BACKGROUND)
- return;
-
- if (AnsiColors == ON)
- {
- memcpy(str, ansi_background, sizeof(ansi_background));
- str[3] += color;
- tty_writes(str, sizeof(ansi_background));
- }
- else
- tty_io_reversevid(color != BLACK);
-
- bg_cache = VALID_CACHE;
-
- TTY_IO_SET_BACKGROUND(color);
- }
-
-
- /*
- * Set the brightness status. See the comment below.
- */
-
- static void
- tty_io_brightness(status)
- int status;
- {
- if (br_cache == VALID_CACHE && status == TTY_IO_BRIGHTNESS)
- return;
-
- if (status == ON)
- {
- if (TTY_BRIGHT_ON)
- tputs(TTY_BRIGHT_ON, 1, tty_writec);
- }
- else
- {
- if (TTY_ATTRIBUTES_OFF)
- tputs(TTY_ATTRIBUTES_OFF, 1, tty_writec);
-
- fg_cache = INVALID_CACHE;
- bg_cache = INVALID_CACHE;
-
- TTY_IO_SET_BRIGHTNESS(OFF);
-
- /* There is no terminal capability to turn the brightness off
- (or the bold mode off). We are using the 'me' capability
- (where available) which turns off all attributes so we must
- restore the reverse status after that.
-
- There is no need to restore the foreground & background
- *colors because we've always put tty_io_brightness(status)
- *BEFORE* tty_io_foreground(color) or
- *tty_io_background(color). */
-
- if (TTY_IO_REVERSEVID == ON)
- {
- rv_cache = INVALID_CACHE;
- tty_io_reversevid(ON);
- }
- }
-
- br_cache = VALID_CACHE;
-
- TTY_IO_SET_BRIGHTNESS(status);
- }
-
-
- /*
- * Set the reverse video status. This is only used internally by the
- * code in this file therefore it is declared 'static'.
- */
-
- static void
- tty_io_reversevid(status)
- int status;
- {
- if (rv_cache == VALID_CACHE && status == TTY_IO_REVERSEVID)
- return;
-
- if (status == ON)
- {
- if (TTY_REVERSE_ON)
- tputs(TTY_REVERSE_ON, 1, tty_writec);
- }
- else
- {
- if (TTY_ATTRIBUTES_OFF)
- tputs(TTY_ATTRIBUTES_OFF, 1, tty_writec);
-
- fg_cache = INVALID_CACHE;
- bg_cache = INVALID_CACHE;
-
- TTY_IO_SET_REVERSEVID(OFF);
-
- /* Same comment as in tty_brightness(). */
- if (TTY_IO_BRIGHTNESS == ON)
- {
- br_cache = INVALID_CACHE;
- tty_io_brightness(ON);
- }
- }
-
- rv_cache = VALID_CACHE;
-
- TTY_IO_SET_REVERSEVID(status);
- }
-
-
- /*
- * Set the brightness, foreground and background all together.
- */
-
- static void
- tty_io_colors(attributes)
- unsigned char attributes;
- {
- tty_io_brightness(_TTY_BRIGHTNESS(attributes));
- tty_io_foreground(_TTY_FOREGROUND(attributes));
- tty_io_background(_TTY_BACKGROUND(attributes));
- }
-
-
- /*
- * Move the cursor.
- */
-
- void
- tty_goto(y, x)
- int y, x;
- {
- tty_cursor_y = y;
- tty_cursor_x = x;
- }
-
-
- /*
- * Set the foreground color.
- */
-
- void
- tty_foreground(color)
- int color;
- {
- TTY_SET_FOREGROUND(color);
- }
-
-
- /*
- * Set the background color.
- */
-
- void
- tty_background(color)
- int color;
- {
- TTY_SET_BACKGROUND(color);
- }
-
-
- /*
- * Set the brightness status. See the comment below.
- */
-
- void
- tty_brightness(status)
- int status;
- {
- TTY_SET_BRIGHTNESS(status);
- }
-
-
- /*
- * Set the reverse video status. This is only used internally by the
- * code in this file therefore it is declared 'static'.
- */
-
- void
- tty_reversevid(status)
- int status;
- {
- TTY_SET_REVERSEVID(status);
- }
-
-
- /*
- * Set the brightness, foreground and background all together.
- */
-
- void
- tty_colors(brightness, foreground, background)
- int brightness, foreground, background;
- {
- tty_brightness(brightness);
- tty_foreground(foreground);
- tty_background(background);
- }
-
-
- /*
- * Beep :-)
- */
-
- void
- tty_beep()
- {
- tty_writec(7);
- tty_flush();
- }
-
-
- /*
- * Set the cursor status (where possible). Make it invisible during screen
- * refreshes and restore it afterward.
- */
-
- void
- tty_cursor(status)
- int status;
- {
- if (status)
- {
- if (TTY_CURSOR_ON)
- tputs(TTY_CURSOR_ON, 1, tty_writec);
- }
- else
- {
- if (TTY_CURSOR_OFF)
- tputs(TTY_CURSOR_OFF, 1, tty_writec);
- }
- }
-
-
- /*
- * Store the software terminal status in a tty_status_t structure.
- */
-
- void
- tty_save(status)
- tty_status_t *status;
- {
- *status = tty_current_attribute;
- }
-
-
- /*
- * Restore the software terminal status from a tty_status_t structure.
- */
-
- void
- tty_restore(status)
- tty_status_t *status;
- {
- tty_current_attribute = *status;
- }
-
-
- /*
- * Restore the terminal to its default state.
- */
-
- void
- tty_defaults()
- {
- if (AnsiColors == ON)
- tty_writes(ansi_defaults, sizeof(ansi_defaults));
-
- if (TTY_ATTRIBUTES_OFF)
- tputs(TTY_ATTRIBUTES_OFF, 1, tty_writec);
-
- fg_cache = INVALID_CACHE;
- bg_cache = INVALID_CACHE;
- br_cache = INVALID_CACHE;
- rv_cache = INVALID_CACHE;
- }
-
-
- /*
- * Get a character from the terminal. For better performance on high loaded
- * systems, read all the data available.
- */
-
- int
- tty_getc()
- {
- if (keyno)
- return keybuf[keyno--, keyindex++];
-
- /* No interrupt/quit character. */
- tty_set_interrupt_char(-1);
-
- for (keyindex = 0; (keyno = tty_read(keybuf, 1024)) < 0;);
-
- /* Restore ^G as the interrupt/quit character. */
- tty_set_interrupt_char(key_INTERRUPT);
-
- return keyno ? keybuf[keyno--, keyindex++] : -1;
- }
-
-
- /*
- * Insert a key sequence into the list.
- */
-
- void
- tty_key_list_insert_sequence(key, key_seq, aux_data)
- tty_key_t **key;
- unsigned char *key_seq;
- void *aux_data;
- {
- tty_key_t *new_key;
-
- new_key = (tty_key_t *)xmalloc(sizeof(tty_key_t));
- new_key->key_seq = (unsigned char *)xstrdup((char *)key_seq);
- new_key->aux_data = aux_data;
- new_key->next = *key;
- *key = new_key;
- }
-
-
- /*
- * Parse the key list, inserting the new key sequence in the proper
- * position.
- */
-
- void
- tty_key_list_insert(key_seq, aux_data)
- unsigned char *key_seq;
- void *aux_data;
- {
- static tty_key_t **key = NULL;
-
- if (*key_seq == 0)
- return; /* bad key sequence ! */
-
- /* Try to optimize by checking if the current entry should be added
- after the current position. Avoid re-parsing the entire list if
- so. */
- if (key == NULL || strcmp((char *)key_seq, (char *)(*key)->key_seq) <= 0)
- key = &key_list_head;
-
- for (; *key; key = &(*key)->next)
- if (strcmp((char *)key_seq, (char *)(*key)->key_seq) <= 0)
- {
- tty_key_list_insert_sequence(key, key_seq, aux_data);
- return;
- }
-
- tty_key_list_insert_sequence(key, key_seq, aux_data);
- }
-
-
- /*
- * Incremental searches a key in the list. Returns a pointer to the first
- * sequence that matches.
- */
-
- tty_key_t *
- tty_key_search(key_seq)
- char *key_seq;
- {
- int cmp;
-
- if (current_key == NULL)
- return NULL;
-
- for (; current_key; current_key = current_key->next)
- {
- cmp = strcmp(key_seq, (char *)current_key->key_seq);
-
- if (cmp == 0)
- return current_key;
-
- if (cmp < 0)
- break;
- }
-
- if (current_key == NULL ||
- strncmp(key_seq, (char *)current_key->key_seq, strlen(key_seq)))
- return (tty_key_t *)-1;
- else
- return NULL;
- }
-
-
- /*
- * Force the next key search to start from the begining of the list.
- */
-
- void
- tty_key_search_restart()
- {
- current_key = key_list_head;
- }
-
-
- #if 0
- /* Delete a key from the list. Don't remove this function, God only knows
- when I'll gonna need it... */
-
- void
- tty_key_list_delete()
- {
- tty_key_t *key, *next_key;
-
- for (key = key_list_head; key; key = next_key)
- {
- next_key = key->next;
- xfree(key->key_seq);
- xfree(key);
- }
- }
- #endif
-
-
- /*
- * Get the first key available, returning also the repeat count, that
- * is, the number of times the key has been pressed. These feature is
- * mainly used by the calling routines to perform optimizations. For
- * example, if you press the down arrow several times, the caller can
- * display only the final position, saving a lot of time. If you have
- * ever worked with git on high loaded systems, I'm sure you know what
- * I mean.
- */
-
- tty_key_t *
- tty_get_key(repeat_count)
- int *repeat_count;
- {
- int i, c;
- tty_key_t *key;
- unsigned char key_seq[64];
-
-
- restart:
-
- while ((c = tty_getc()) == -1);
-
- if (repeat_count)
- *repeat_count = 1;
-
- /* Handle ^SPC. */
- if (c == 0)
- c = 0xff;
-
- if (!tty_kbdmode)
- {
- if (c == '\n' || c == '\r')
- c = key_ENTER;
-
- if (is_print(c) || c == key_INTERRUPT)
- {
- default_key.key_seq[0] = c;
- default_key.key_seq[1] = 0;
- return &default_key;
- }
- }
-
- tty_key_search_restart();
-
- for (i = 0; i < MAX_KEY_LENGTH; i++)
- {
- /* Handle brain-damaged key sequences correctly. If a 0 is
- found, transform it in a 0xff. I don't know how smart this
- is, but right know I don't feel like doing it otherwise. */
- if (c == 0)
- c = 0xff;
-
- key_seq[i ] = c;
- key_seq[i + 1] = 0;
-
- key = tty_key_search((char *)key_seq);
-
- if (key == (tty_key_t *)-1)
- goto restart;
-
- if (key)
- break;
-
- while ((c = tty_getc()) == -1);
- }
-
- if (i == MAX_KEY_LENGTH)
- goto restart;
-
- if (repeat_count)
- while (keyno > i && (memcmp(key_seq, &keybuf[keyindex], i + 1) == 0))
- {
- keyindex += i + 1;
- keyno -= i + 1;
- (*repeat_count)++;
- }
-
- return key;
- }
-
-
- /*
- * Retreive the screen size. Try ioctl(TIOCGWINSZ, ...) and, if it fails
- * or it is not supported, use the environment variables LINES & COLUMNS
- * (if possible). If both methods fail, use the default 80x24.
- */
-
- void
- tty_get_size(_columns, _lines)
- int *_columns, *_lines;
- {
- char *env;
-
- #ifdef HAVE_WINSZ
- int result;
- struct winsize winsz;
- int winsz_lines = 0, winsz_columns = 0;
- #endif /* HAVE_WINSZ */
-
- columns = lines = 0;
-
- #ifdef HAVE_WINSZ
-
- #if defined TIOCGSIZE && !defined TIOCGWINSZ
- #define TIOCGWINSZ TIOCGSIZE
- #endif
-
- result = ioctl(TTY_OUTPUT, TIOCGWINSZ, &winsz);
-
- if (result == 0)
- if (winsz.ws_col && winsz.ws_row)
- {
- winsz_columns = winsz.ws_col;
- winsz_lines = winsz.ws_row;
- }
-
- if (winsz_columns < MIN_TTY_COLUMNS || winsz_columns > MAX_TTY_COLUMNS)
- winsz_columns = 80;
-
- if (winsz_lines < MIN_TTY_LINES || winsz_lines > MAX_TTY_LINES)
- winsz_lines = 24;
-
- #endif /* HAVE_WINSZ */
-
- if ((env = getenv("COLUMNS")))
- sscanf(env, "%d", &columns);
-
- if ((env = getenv("LINES")))
- sscanf(env, "%d", &lines);
-
- if (columns < MIN_TTY_COLUMNS || columns > MAX_TTY_COLUMNS)
- {
- #ifdef HAVE_WINSZ
- columns = winsz_columns;
- #else
- columns = 80;
- #endif /* HAVE_WINSZ */
- }
-
- if (lines < MIN_TTY_LINES || lines > MAX_TTY_LINES)
- {
- #ifdef HAVE_WINSZ
- lines = winsz_lines;
- #else
- lines = 24;
- #endif /* HAVE_WINSZ */
- }
-
- *_columns = columns;
- *_lines = lines;
- }
-
-
- #ifdef HAVE_LINUX
- /*
- * Read and write the screen contents via a Linux virtual console.
- * Returns 0 on failure, non-zero otherwise. Handle both /dev/vcsaX
- * and /dev/vcsX. op specifies the operation to be performed: VCS_READ
- * or VCS_WRITE. We check first for /dev/vcs?X since it makes debugging
- * easier (using /de/vcsa0 when debugging dumps the screen on the
- * debugger's console; not funny).
- */
-
- int
- vcs_io(buf, op)
- char *buf;
- int op;
- {
- int (*fn)();
- int vcsfd, flag;
- char vcs_name[16] = "/dev/vcsX";
- char vcsa_name[16] = "/dev/vcsaX";
-
- if (op == VCS_READ)
- {
- flag = O_RDONLY;
- fn = read;
- }
- else
- {
- flag = O_WRONLY;
- fn = write;
-
- if (vcs_is_bw)
- goto bw_label;
- }
-
- vcs_is_bw = 0;
-
- /* First attempt: /dev/vcsaX. */
- vcsa_name[9] = tty_name[tty_name_len - 1];
- vcsfd = open(vcsa_name, flag);
-
- if (vcsfd != -1)
- {
- vcsa_label:
- (*fn)(vcsfd, buf, 4 + lines * columns * 2);
- close(vcsfd);
-
- if (op == VCS_WRITE)
- {
- tty_io_goto(buf[3], buf[2]);
- tty_flush();
- }
-
- return 1;
- }
-
- /* Second attempt: /dev/vcsa0. */
- vcsa_name[9] = '0';
- vcsfd = open(vcsa_name, flag);
-
- if (vcsfd != -1)
- goto vcsa_label;
-
- bw_label:
-
- /* We failed to access a /dev/vcsa* device. */
- vcs_is_bw = 1;
-
- /* This is important in order to clear the screen attributes. */
- if (op == VCS_WRITE)
- tty_clear();
-
- /* Third attempt: /dev/vcsX (B/W). */
- vcs_name[8] = tty_name[tty_name_len - 1];
- vcsfd = open(vcs_name, flag);
-
- if (vcsfd != -1)
- {
- vcs_label:
- (*fn)(vcsfd, buf, 4 + lines * columns);
- close(vcsfd);
-
- /* Unfortunately, the b/w devices do not provide the 4 bytes header
- with screen size & cursor position information. */
-
- if (op == VCS_WRITE)
- {
- tty_io_goto(lines - 1, 0);
- tty_flush();
- }
- return 1;
- }
-
- /* Fourth attempt: /dev/vcs0 (B/W). */
- vcs_name[8] = '0';
- vcsfd = open(vcs_name, flag);
-
- if (vcsfd != -1)
- goto vcs_label;
-
- return 0;
- }
- #endif
-
-
- /*
- * Dump the screen. Only used in Linux if the terminal is a virtual
- * console.
- */
-
- void
- tty_get_screen(buf)
- char *buf;
- {
- #ifdef HAVE_LINUX
- if (LinuxConsole)
- vcs_read_ok = vcs_io(buf, VCS_READ);
- #endif /* HAVE_LINUX */
- }
-
-
- /*
- * Restore the screen. If the terminal is not a Linux virtual console, just
- * restore it to the default state.
- */
-
- void
- tty_put_screen(buf)
- char *buf;
- {
- tty_defaults();
-
- #ifdef HAVE_LINUX
- if (LinuxConsole)
- {
- /* If we were unable to read from /dev/vcs*, then we should not
- try to restore it. */
- if (vcs_read_ok)
- {
- tty_touch();
-
- /* We might have the permission to read the contents of the
- virtual console, but not the permission to write it. */
- if (vcs_io(buf, VCS_WRITE) == 0)
- tty_clear();
- else
- memset(tty_scr, '\0', lines * columns * sizeof(unsigned char));
- }
- else
- tty_clear();
- }
- else
- tty_clear();
- #else /* !HAVE_LINUX */
- tty_clear();
- #endif /* !HAVE_LINUX */
- }
-
-
- /*
- * Get the color index from the colors[] index table.
- */
-
- int
- tty_get_color_index(colorname)
- char *colorname;
- {
- int i;
-
- for (i = 0; i < 10; i++)
- if (strcmp(colors[i], colorname) == 0)
- return (i < 8) ? i : (i - 8);
-
- return -1;
- }
-
-
- /*
- * Return the capability of a given termcap symbol.
- */
-
- char *
- tty_get_symbol_key_seq(symbol)
- char *symbol;
- {
- int i;
-
- for (i = TTY_FIRST_SYMBOL_KEY; i < TTY_USED_CAPABILITIES; i++)
- if (strcmp(tty_capability[i].symbol, symbol) == 0)
- return tty_capability[i].string;
-
- return NULL;
- }
-
-
- /*
- * Get the entire set of requiresd termcap/terminfo capabilities. It performs
- * consistency checkings trying to recover as well as possible.
- */
-
- void
- tty_get_capabilities()
- {
- #ifdef HAVE_LINUX
- struct stat statbuf;
- #endif /* HAVE_LINUX */
- char *capability_buf, *tmp;
- int err, i, term_errors = 0;
- char *termtype = getenv("TERM");
-
- #ifdef HAVE_LINUX
- fstat(TTY_OUTPUT, &statbuf);
- if ((statbuf.st_rdev >> 8) == LINUX_VC_MAJOR &&
- ((unsigned)(statbuf.st_rdev & 0xFF)) <= 8)
- LinuxConsole = 1;
- else
- LinuxConsole = 0;
- #endif /* HAVE_LINUX */
-
- if (termtype == NULL)
- {
- fprintf(stderr, "%s: can't find the TERM environment variable, ",
- program);
- goto switch_to_vt100;
- }
-
- if (strlen(termtype) > 63)
- {
- fprintf(stderr, "%s: the TERM environment variable is too long, ",
- program);
- switch_to_vt100:
- fprintf(stderr, "trying vt100 ...\n");
- termtype = vt100;
- }
-
- err = tgetent(term_buf, termtype);
-
- if (err == -1)
- {
- fprintf(stderr, "%s: can't find the %s database.\n",
- program, term_database);
- fprintf(stderr, "%s: check your %s environment variable ...\n",
- program, term_env);
- exit(1);
- }
-
- if (err == 0)
- {
- fprintf(stderr,
- "%s: can't find the terminal type %s in the %s database.\n",
- program, termtype, term_database);
- exit(1);
- }
-
- tty_type = xstrdup(termtype);
-
- capability_buf = xmalloc(2048);
-
- tmp = tgetstr(TTY_PAD_CHAR_NAME, &capability_buf);
- PC = tmp ? *tmp : 0;
-
- BC = tgetstr(TTY_LEFT_ONE_SPACE_NAME, &capability_buf);
- UP = tgetstr(TTY_UP_ONE_LINE_NAME, &capability_buf);
-
- if (BC == NULL || UP == NULL)
- BC = UP = NULL;
-
- TTY_ATTRIBUTES_OFF = tgetstr(TTY_ATTRIBUTES_OFF_NAME, &capability_buf);
- TTY_BRIGHT_ON = tgetstr(TTY_BRIGHT_ON_NAME, &capability_buf);
- TTY_REVERSE_ON = tgetstr(TTY_REVERSE_ON_NAME, &capability_buf);
-
- if (TTY_ATTRIBUTES_OFF == NULL)
- TTY_REVERSE_ON = TTY_BRIGHT_ON = NULL;
-
- TTY_STANDOUT_ON = tgetstr(TTY_STANDOUT_ON_NAME, &capability_buf);
-
- if (TTY_STANDOUT_ON == NULL)
- {
- TTY_STANDOUT_ON = NULL;
- TTY_MS_FLAG = 0;
- }
- else
- {
- /* Use standout instead of reverse video whenever possible. */
- TTY_REVERSE_ON = TTY_STANDOUT_ON;
- TTY_MS_FLAG = tgetflag(TTY_MS_FLAG_NAME);
- }
-
- /* Check for magic-cookie terminals. Not supported yet. */
- TTY_MAGIC_COOKIE = tgetnum(TTY_MAGIC_COOKIE_NAME);
-
- if (TTY_MAGIC_COOKIE >= 0)
- TTY_ATTRIBUTES_OFF = TTY_REVERSE_ON = TTY_BRIGHT_ON = NULL;
-
-
- TTY_CURSOR_OFF = tgetstr(TTY_CURSOR_OFF_NAME, &capability_buf);
- TTY_CURSOR_ON = tgetstr(TTY_CURSOR_ON_NAME, &capability_buf);
-
- if (TTY_CURSOR_OFF == NULL || TTY_CURSOR_ON == NULL)
- TTY_CURSOR_ON = TTY_CURSOR_OFF = NULL;
-
- TTY_CLEAR_SCREEN = tgetstr(TTY_CLEAR_SCREEN_NAME, &capability_buf);
- TTY_CURSOR_MOVE = tgetstr(TTY_CURSOR_MOVE_NAME, &capability_buf);
-
- for (i = TTY_FIRST_SYMBOL_KEY; i < TTY_USED_CAPABILITIES; i++)
- tty_capability[i].string = tgetstr(tty_capability[i].name,
- &capability_buf);
-
- for (i = 0; i < TTY_USED_CAPABILITIES; i++)
- if (tty_capability[i].string == NULL)
- if (tty_capability[i].required)
- {
- term_errors++;
- fprintf(stderr,
- "%s: can't find the '%s' terminal capability.\n",
- program, tty_capability[i].name);
- }
-
- if (term_errors)
- {
- fprintf(stderr, "%s: %d errors. Your terminal is too dumb :-< .\n",
- program, term_errors);
- exit(1);
- }
- }
-